package cn.demoncat;

import cn.demoncat.test.neo.dao.*;
import cn.demoncat.test.neo.node.*;
import cn.demoncat.util.lang.CollectionUtil;
import cn.demoncat.util.web.constant.AppConstant;
import cn.demoncat.util.lang.entity.MapSo;
import cn.demoncat.util.lang.entity.Result;
import cn.demoncat.util.web.annotation.GetJsonMapping;
import org.springframework.boot.SpringApplication;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;

/**
 * 启动入口
 *
 * @author 延晓磊
 * @since 2021年03月26日
 */
// @WebApp
@RestController
public class App {

    @Resource
    private IdStringAutoRepository idStringAutoRepository;
    @Resource
    private IdStringRepository idStringRepository;
    @Resource
    private IdLongAutoRepository idLongAutoRepository;
    @Resource
    private RUserRelationRepository rUserRelationRepository;
    @Resource
    private RUserRepository rUserRepository;
    @Resource
    private RFoodRepository rFoodRepository;

    public static void main(String[] args) {
        AppConstant.CONTEXT = SpringApplication.run(App.class, args);
    }

    /**
     * 1、保存
     * 2、查询
     * 3、ID规则
     */
    @Transactional
    @GetJsonMapping("/id")
    public Result testId(String id){
        String name = "name - " + System.currentTimeMillis();

        // Long Auto Id 自增
        IdLongAutoNode idLongAutoNode = new IdLongAutoNode();
        idLongAutoNode.setId(null);
        idLongAutoNode.setName(name);
        idLongAutoNode.setOther("id long auto");
        idLongAutoRepository.save(idLongAutoNode);

        // Long Auto Id 更新（不存在时忽略）
        idLongAutoNode = new IdLongAutoNode();
        idLongAutoNode.setId(Long.valueOf(id));
        idLongAutoNode.setName(name);
        idLongAutoNode.setOther("id long auto");
        idLongAutoRepository.save(idLongAutoNode);

        // String Auto Id 自增
        IdStringAutoNode idStringAutoNode = new IdStringAutoNode();
        idStringAutoNode.setId(null);
        idStringAutoNode.setName(name);
        idStringAutoNode.setOther("id string auto");
        idStringAutoRepository.save(idStringAutoNode);

        // String Auto Id 添加/更新（存在时更新，不存在时添加）
        idStringAutoNode = new IdStringAutoNode();
        idStringAutoNode.setId(id);
        idStringAutoNode.setName(name);
        idStringAutoNode.setOther("id string auto");
        idStringAutoRepository.save(idStringAutoNode);

        // String Auto Id 添加/更新（存在时更新，不存在时添加）
        IdStringNode idStringNode = new IdStringNode();
        idStringNode.setId(id);
        idStringNode.setName(name);
        idStringNode.setOther("id string");
        idStringRepository.save(idStringNode);

        return Result.success(MapSo.getInstance(
                "id long auto",  idLongAutoRepository.findAll(),
                "id string auto",  idStringAutoRepository.findAll(),
                "id string",  idStringRepository.findAll()

        ));
    }

    /**
     * 1、关系
     * 2、JAP查询
     * 3、Cypher查询
     */
    @Transactional
    @GetJsonMapping("/relation")
    public Result testRelation(){
        // 用户（节点）
        RUserNode user1 = new RUserNode();
        user1.setName("u1-"+System.currentTimeMillis());
        RUserNode user2 = new RUserNode();
        user2.setName("u2-"+System.currentTimeMillis());
        RUserNode user3 = new RUserNode();
        user3.setName("u3-"+System.currentTimeMillis());

        // 直接关联（关系）
        user1.setFriends(CollectionUtil.toList(user2, user3));

        // 食品（节点）
        RFoodNode food1 = new RFoodNode();
        food1.setName("f1-"+System.currentTimeMillis());
        RFoodNode food2 = new RFoodNode();
        food2.setName("f2-"+System.currentTimeMillis());

        // 间接关联（关系）
        RUserRelation relation1 = new RUserRelation();
        relation1.setName("r1-"+System.currentTimeMillis());
        relation1.setUser(user1);
        relation1.setFood(food1);
        RUserRelation relation2 = new RUserRelation();
        relation2.setName("r2-"+System.currentTimeMillis());
        relation2.setUser(user2);
        relation2.setFood(food2);
        RUserRelation relation3 = new RUserRelation();
        relation3.setName("r3-"+System.currentTimeMillis());
        relation3.setUser(user3);
        relation3.setFood(food2);

        // 保存节点：同时保存关联的节点、关系（直接关联，无属性）
        // rUserRepository.save(user1);

        // 保存节点
        // rFoodRepository.saveAll(CollectionUtil.toList(food1, food2));

        // 保存关系：同时保存关联的节点（间接关联，有属性；保存节点时同时保存直接关联的节点和关系）
        rUserRelationRepository.saveAll(CollectionUtil.toList(relation1, relation2, relation3));

        // 查询：关联关系需要前置处理，防止循环依赖导致JSON序列化时StackOverflowError
        return Result.success(MapSo.getInstance(
               "users",  RUserNode.beforeJson(rUserRepository.findAll()),
                "foods",  rFoodRepository.findAll(),
                "relations",  RUserRelation.beforeJson(rUserRelationRepository.findAll()),
                "JPA", RUserNode.beforeJson(rUserRepository.findByName(user2.getName())),
                "Cypher", RUserNode.beforeJson(rUserRepository.getUserByName(user1.getName()))
        ));
    }

}
